//
// Created by wxd on 2025/7/21.
// 测试相机矩阵
//

// NOTE: 常用快捷键
// ctrl + tab: 切换历史文件
// ctrl + shift + N: 跳转类文件
// ctrl + N: 跳转类
// ctrl + G: 跳行
// ctrl + B: 跳转方法
// alt + 1: 索引项目视图
// alt + insert: 创建文件
//

#pragma once

#include <iostream>
#include <vector>
#include <glm/glm.hpp>
#include <glm/trigonometric.hpp>
#include "../wrapper/log/Logger.h"
#include "../wrapper/monitor/GLDebug.hpp"
#include "../global/ChineseOutput.hpp"
#include "../global/EngineDataProperties.h"
#include "../application/app/Application.h"
#include "../glFramework/shader/Shader.h"
#include "../glFramework/constant/engine_layout.h"
#include "../glFramework/texture/Texture.h"
#include "../glFramework/utils/ResourceLoadUtils.h"
#include "../glFramework/bo/VBO.h"
#include "../glFramework/bo/VAO.h"
#include "../glFramework/constant/engine_uniform.h"
#include <memory>

#include "bo/EBO.h"
#include "../global/output.hpp"

// Note: glm数学库中的矩阵是主列的

// 创建相机矩阵
/* 运行结果：最后一列不同，其余都是相同的
glm_camera:
[        -1,          0,          0,         -0]
[         0,   0.707107,   0.707107,         -0]
[        -0,   0.707107,  -0.707107,   -1.41421]
[         0,          0,          0,          1]

camera:
[        -1,          0,          0,          0]
[         0,   0.707107,   0.707107,         -1]
[         0,   0.707107,  -0.707107,          1]
[         0,          0,          0,          1]
*/
/*inline glm::mat4 lookAt(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
    // 构建相机坐标系 {Right, Up, Front} -> {+x, +y, -z}
    glm::vec3 Front = glm::normalize(target - eye);
    glm::vec3 Right = glm::normalize(glm::cross(Front, up));
    glm::vec3 Up = glm::normalize(glm::cross(Right, Front));

    // 旋转相机，将相机旋转到与{(1,0,0), (0,1,0), (0,0,-1)}方向重叠， rot^- = {Right, Up, Front} -> rot^T = {Right, Up, Front}
    glm::mat4 rot = glm::mat4(0.f);
    rot[0] = glm::vec4(Right, 0.f);
    rot[1] = glm::vec4(Up, 0.f);
    rot[2] = glm::vec4(-Front, 0.f);
    rot[3] = glm::vec4(0.f, 0.f, 0.f, 1.f);

    // 移动相机，将相机移动到世界坐标系下的原点
    glm::mat4 trans = glm::mat4(1.f);
    trans[3] = glm::vec4(-eye, 1.f);

    return trans * rot;
}*/
/**
 * 通过分析glm::lookAt的源码，走的Right-Hand坐标系的函数：lookAtRH(eye, center, up)
*       vec<3, T, Q> const f(normalize(center - eye));
        vec<3, T, Q> const s(normalize(cross(f, up)));
        vec<3, T, Q> const u(cross(s, f));
 */
/*inline glm::mat4 lookAt(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
    glm::vec3 Front = glm::normalize(target - eye);
    glm::vec3 Left = glm::normalize(glm::cross(Front, up));
    glm::vec3 Up = glm::normalize(glm::cross(Left, Front));

    // {Left, Up, Front} -> {-x, +y, +z}: rot {Left, Up, Front} = {-e1, e2, e3}
    // rot {-Left, Up, Front} = {e1, e2, e3} -> rot^-1 = {-Left, Up, Front} -> rot^T = rot^-1
    glm::mat4 rot = glm::mat4(1.f);
    rot[0] = glm::vec4(-Left, 0.f);
    rot[1] = glm::vec4(Up, 0.f);
    rot[2] = glm::vec4(Front, 0.f);
    rot[3] = glm::vec4(0.f, 0.f, 0.f, 1.f);

    glm::mat4 trans = glm::mat4(1.f);
    trans[3] = glm::vec4(-eye, 1.f);

    return trans * rot;
}*/

/*inline glm::mat4 lookAt(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
    // 修正1：Front 方向与 GLM 一致（看向 -Z）
    glm::vec3 Front = glm::normalize(eye - target);

    // 修正2：叉积顺序与 GLM 一致（up × Front）
    glm::vec3 Right = glm::normalize(glm::cross(up, Front));

    // 修正3：重新正交化 Up（Front × Right）
    glm::vec3 Up = glm::normalize(glm::cross(Front, Right));

    // 旋转矩阵的列向量：Right, Up, Front（列主序）
    glm::mat4 rot = glm::mat4(1.0f);
    rot[0] = glm::vec4(Right, 0.0f);   // 第 1 列
    rot[1] = glm::vec4(Up, 0.0f);      // 第 2 列
    rot[2] = glm::vec4(Front, 0.0f);   // 第 3 列

    // 平移矩阵（将相机移动到原点）
    glm::mat4 trans = glm::mat4(1.0f);
    trans[3] = glm::vec4(-eye, 1.0f);

    return trans * rot; // 先旋转，再平移
}*/

/*inline glm::mat4 lookAt(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
    // 完全按照GLM的方式计算
    glm::vec3 Front = glm::normalize(eye - target);
    glm::vec3 Right = glm::normalize(glm::cross(glm::normalize(up), Front));
    glm::vec3 Up = glm::cross(Front, Right);

    glm::mat4 rot = glm::mat4(1.0f);
    rot[0][0] = Right.x; rot[1][0] = Right.y; rot[2][0] = Right.z;
    rot[0][1] = Up.x;    rot[1][1] = Up.y;    rot[2][1] = Up.z;
    rot[0][2] = Front.x; rot[1][2] = Front.y; rot[2][2] = Front.z;

    glm::mat4 trans = glm::mat4(1.0f);
    trans[3][0] = -eye.x; trans[3][1] = -eye.y; trans[3][2] = -eye.z;

    return trans * rot;
}*/

// 上面给出的三个函数最终输出的相机矩阵和glm提供的均不同，核心问题在于glm中的平移是投影平移，而非当前给出代码的直接平移
// 这里的投影平移可以理解为：针对相机坐标系{Right, Up, -Front} 基于eye方向做投影（相当于将eye位置的相机摆正，然后在平移到原点，先做旋转，在平移，平移之前保证旋转之后的局部坐标和平移坐标系相同即可）
inline glm::mat4 lookAt(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
    // 构建相机坐标系 {Left, Up, Look} = {-x, +y, +z}
    glm::vec3 Look = glm::normalize(target - eye);
    glm::vec3 Left = glm::normalize(glm::cross(Look, up));
    glm::vec3 Up = glm::normalize(glm::cross(Left, Look));

    // 希望将{Left, Up, Look} ——> {x, y, -z}
    // 计算相机的旋转矩阵: rot {-Left, Up, Look} = {x, y, z} -> rot^-1 = {-Left, Up, Look} -> rot^T = rot^-1
    glm::mat4 rot = glm::mat4(1.f);
    rot[0] = glm::vec4(-Left, 0.f);
    rot[1] = glm::vec4(Up, 0.f);
    rot[2] = glm::vec4(-Look, 0.f);
    rot[3] = glm::vec4(0.f, 0.f, 0.f, 1.f);

    glm::mat4 trans = glm::mat4(1.f);
    // x,y的移动是从+轴还是，所以是移动符号是-，但是z是朝向-z的，所以为+号
    trans[3] = glm::vec4(-glm::dot(eye, -Left), -glm::dot(eye, Up), -glm::dot(eye, -Look), 1.f);

    return trans * rot;
}

inline void render() {
    glm::mat4 glm_camera = glm::lookAt(glm::vec3(0.f, 1.f, 4.f), glm::vec3(0.f), glm::vec3(0.f, 1.f, 1.f));
    glm::mat4 camera = lookAt(glm::vec3(0.f, 1.f, 4.f), glm::vec3(0.f), glm::vec3(0.f, 1.f, 1.f));

    EngineOutput::outputMatrix("glm_camera", glm_camera);
    EngineOutput::outputMatrix("camera", camera);
}